home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / timer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  5.4 KB  |  238 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "timer.h"
  4. #include "proc.h"
  5. #include "commands.h"
  6. #include "daemon.h"
  7. #include "hardware.h"
  8. #include "socket.h"
  9.  
  10. /* Head of running timer chain.
  11.  * The list of running timers is sorted in increasing order of interval;
  12.  * i.e., the first timer to expire is always at the head of the list.
  13.  * For performance reasons, the intervals are incremental, so that only
  14.  * the first entry needs to be decremented on each tick. Hence there are
  15.  * special routines for reading the number of ticks remaining on a
  16.  * running timer; you can't just look at the field directly.
  17.  */
  18. static struct timer *Timers;
  19.  
  20. /* This variable keeps a running count of ticks since program startup */
  21. int32 Clock;
  22.  
  23. static void t_alarm(void *x);
  24.  
  25. /* Process that handles clock ticks */
  26. void
  27. timerproc(i,v1,v2)
  28. int i;
  29. void *v1,*v2;
  30. {
  31.     register struct timer *t, *p;
  32.     register struct timer *expired = NULLTIMER;
  33.     char i_state;
  34.  
  35.     for(;;){
  36.         i_state = dirps();    /* Tick is modified by an interrupt */
  37.         while(Tick == 0)
  38.             pwait(&Tick);
  39.         Tick--;
  40.         restore(i_state);
  41.  
  42.         Clock++;    /* Keep system time */
  43.         systick();    /* Machine-dependent per-tick stuff */
  44.         tflush();    /* Flush current session output */
  45.         pwait(NULL);    /* Let them all do their writes */
  46.         fflush(stdout);    /* Flush out buffered console stuff */
  47.  
  48.         if(Timers == NULLTIMER)
  49.             continue;    /* Nothing to do on this tick */
  50.  
  51.         /* Decrement the first timer. If it expires,
  52.          * take it off the running list and put it
  53.          * on a singly linked list of expired timers
  54.          */
  55.         Timers->count--;
  56.  
  57.         /* initialize null expired timer list */
  58.         expired = NULLTIMER;
  59.  
  60.         while(Timers != NULLTIMER && Timers->count <= 0){
  61.             if(Timers->next == Timers){
  62.                 printf("PANIC: Timer loop at %lx\n",
  63.                  (long)Timers);
  64.                 iostop();
  65.                 exit(1);
  66.             }
  67.             /* Save Timers since stop_timer will change it */
  68.             t = Timers;
  69.             stop_timer(t);
  70.             /* Add to expired timer list */
  71.             if(expired == NULLTIMER){
  72.                 expired = t;        /* First one on chain */
  73.             } else {
  74.                 for(p = expired ; p->next != NULLTIMER ; p = p->next);
  75.                 p->next = t;        /* place at END of chain */
  76.             }
  77.  
  78.             t->next = NULLTIMER;
  79.         }
  80.         /* Now go through the list of expired timers, removing each
  81.          * one and kicking the notify function, if there is one
  82.          */
  83.         while((t = expired) != NULLTIMER){
  84.             t->state = TIMER_EXPIRE;
  85.             expired = t->next;
  86.             if(t->func){
  87.                 (*t->func)(t->arg);
  88.             }
  89.         }
  90.         pwait(NULL);    /* Let them run before handling more ticks */
  91.     }
  92. }
  93. /* Start a timer */
  94. void
  95. start_timer(t)
  96. struct timer *t;
  97. {
  98.     register struct timer *tnext,*tprev;
  99.     int32 tot;
  100.  
  101.     if(t == NULLTIMER)
  102.         return;
  103.     if(t->state == TIMER_RUN)
  104.         stop_timer(t);
  105.     if(t->start == 0) {
  106.         t->count = 0;    /* remove -1 from count field */
  107.         return;        /* A start value of 0 disables the timer */
  108.     }
  109.  
  110.     t->state = TIMER_RUN;
  111.     /* Find right place on list for this guy */
  112.     tot = 0;
  113.     tprev = NULLTIMER;
  114.     for(tnext = Timers;tnext != NULLTIMER;tnext = tprev->next){
  115.         if(tnext->count + tot > t->start)
  116.             break;
  117.         tprev = tnext;
  118.         tot += tnext->count;
  119.     }
  120.     /* At this point, tprev points to the entry that should go right
  121.      * before us, and tnext points to the entry just after us. Either or
  122.      * both may be null.
  123.      */
  124.     t->count = t->start - tot;    /* Adjust for entries before us */
  125.     if((t->prev = tprev) == NULLTIMER)
  126.         Timers = t;        /* Put at beginning */
  127.     else
  128.         tprev->next = t;
  129.  
  130.     if((t->next = tnext) != NULLTIMER){
  131.         tnext->prev = t;
  132.         /* Adjust the following entry's count */
  133.         tnext->count -= t->count;
  134.     }
  135. }
  136. /* Stop a timer */
  137. void
  138. stop_timer(t)
  139. register struct timer *t;
  140. {
  141.     register struct timer *tp;
  142.  
  143.     if(t == NULLTIMER)
  144.         return;
  145.     if(t->state == TIMER_RUN){
  146.         /* Delete from active timer list */
  147.         if(t->next != NULLTIMER)
  148.             t->next->prev = t->prev;
  149.         if(t->prev != NULLTIMER)
  150.             t->prev->next = t->next;
  151.         else
  152.             Timers = t->next;
  153.         /* Adjust count for the next timer */
  154.         if((tp = t->next) != NULLTIMER)
  155.             tp->count += t->count;
  156.     }
  157.     t->state = TIMER_STOP;
  158.     t->next  = NULLTIMER;        /* just being tidy */
  159.     t->prev  = NULLTIMER;
  160. }
  161. /* Return count of ticks remaining on this timer */
  162. int32
  163. read_timer(t)
  164. struct timer *t;
  165. {
  166.     register struct timer *tp;
  167.     int32 tot;
  168.  
  169.     if(t->state != TIMER_RUN)
  170.         return 0;
  171.  
  172.     tot = 0;
  173.     for(tp = Timers;tp != NULLTIMER; tp = tp->next){
  174.         tot += tp->count;
  175.         if(tp == t)
  176.             break;
  177.     }
  178.     return tot;
  179. }
  180. /* Delay process for specified number of ticks.
  181.  * Normally returns 0; returns -1 if aborted by alarm.
  182.  */
  183. int
  184. pause(ticks)
  185. int32 ticks;
  186. {
  187.     int val;
  188.  
  189.     if(Curproc == NULLPROC || ticks == 0)
  190.         return 0;
  191.     alarm(ticks);
  192.     /* The actual event doesn't matter, since we'll be alerted */
  193.     while(Curproc->alarm.state == TIMER_RUN){
  194.         if((val = pwait(Curproc)) != 0)
  195.             break;
  196.     }
  197.     alarm(0L); /* Make sure it's stopped, in case we were killed */    
  198.     return (val == EALARM) ? 0 : -1;
  199. }
  200. static void
  201. t_alarm(x)
  202. void *x;
  203. {
  204.     alert((struct proc *)x,EALARM);
  205. }
  206. /* Send signal to current process after specified number of ticks */
  207. void
  208. alarm(ticks)
  209. int32 ticks;
  210. {
  211.     if(Curproc != NULLPROC){
  212.         Curproc->alarm.start = ticks;
  213.         Curproc->alarm.func = t_alarm;
  214.         Curproc->alarm.arg = (char *)Curproc;
  215.         start_timer(&Curproc->alarm);
  216.     }
  217. }
  218. /* Convert time count in ticks to printable days:hr:min:sec format */
  219. char *
  220. tformat(t)
  221. int32 t;
  222. {
  223.     static char buf[16];
  224.     unsigned int days,hrs,mins,secs;
  225.  
  226.     t = (t * MSPTICK) / 1000;    /* Convert to seconds */
  227.     secs = t % 60;
  228.     t /= 60;
  229.     mins = t % 60;
  230.     t /= 60;
  231.     hrs = t % 24;
  232.     t /= 24;
  233.     days = t;
  234.     sprintf(buf,"%u:%02u:%02u:%02u",days,hrs,mins,secs);
  235.     return buf;
  236. }
  237.     
  238.